home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow_WinXP / VMR / VMRXcl / app.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  20.7 KB  |  812 lines

  1. //----------------------------------------------------------------------------
  2. //  File:   app.cpp
  3. //
  4. //  Desc:   DirectShow sample code
  5. //          Main module for customized video player in exclusive mode
  6. //
  7. //  Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
  8. //----------------------------------------------------------------------------
  9.  
  10. #include "project.h"
  11. #include <atlbase.h>
  12. #include <atlconv.cpp>
  13. #include <mmreg.h>
  14. #include <commctrl.h>
  15.  
  16. #include <stdarg.h>
  17. #include <stdio.h>
  18.  
  19. #include "utils.h"
  20.  
  21. /* -------------------------------------------------------------------------
  22. ** Global variables that are initialized at run time and then stay constant.
  23. ** -------------------------------------------------------------------------
  24. */
  25. HINSTANCE           g_hInst;
  26. HICON               hIconVideoCd;
  27. HWND                hwndApp;
  28. HWND                g_hwndToolbar;
  29. CMpegMovie          *pMpegMovie;
  30. BOOL                g_bPlay = FALSE;
  31.  
  32. /* -------------------------------------------------------------------------
  33. ** True Globals - these may change during execution of the program.
  34. ** -------------------------------------------------------------------------
  35. */
  36. TCHAR               g_achFileName[MAX_PATH];
  37. DWORD               g_State = VCD_NO_CD;
  38. BOOL                g_bFullScreen = FALSE;
  39.  
  40.  
  41. struct SceneSettings g_ss;
  42.  
  43. const LONG  g_Style =  WS_POPUP | WS_CAPTION | WS_SYSMENU;
  44.  
  45.  
  46. /* -------------------------------------------------------------------------
  47. ** Constants
  48. ** -------------------------------------------------------------------------
  49. */
  50. const TCHAR szClassName[] = TEXT("VMRXCLPlayer_CLASS");
  51. const TCHAR g_szNULL[]    = TEXT("\0");
  52. const TCHAR g_szEmpty[]   = TEXT("");
  53.  
  54. typedef enum VMRXcl_menu
  55. {
  56.     evxShowInfo  = 0x0,
  57.     evxMoviePause,
  58.     evxMoviePlay,
  59.     evxMovieRotateZ,
  60.     evxMovieRotateY,
  61.     evxMovieTwist,
  62.     evxMovieOption4,
  63.     evxExit,
  64.  
  65. } VMRXcl_menu;
  66.  
  67.  
  68. void SetFullScreenMode(BOOL bMode);
  69. BOOL IsFullScreenMode();
  70. extern BOOL VerifyVMR(void);
  71.  
  72.  
  73. /******************************Public*Routine******************************\
  74. * WinMain
  75. *
  76. *
  77. * Windows recognizes this function by name as the initial entry point
  78. * for the program.  This function calls the application initialization
  79. * routine, if no other instance of the program is running, and always
  80. * calls the instance initialization routine.  It then executes a message
  81. * retrieval and dispatch loop that is the top-level control structure
  82. * for the remainder of execution.  The loop is terminated when a WM_QUIT
  83. * message is received, at which time this function exits the application
  84. * instance by returning the value passed by PostQuitMessage().
  85. *
  86. * If this function must abort before entering the message loop, it
  87. * returns the conventional value NULL.
  88. *
  89. \**************************************************************************/
  90. int PASCAL
  91. WinMain(
  92.     HINSTANCE hInstance,
  93.     HINSTANCE hPrevInstance,
  94.     LPSTR lpCmdLineOld,
  95.     int nCmdShow
  96.     )
  97. {
  98.     USES_CONVERSION;
  99.     int iRet=0;
  100.     LPTSTR lpCmdLine = A2T(lpCmdLineOld);
  101.  
  102.     HRESULT hres = CoInitialize(NULL);
  103.     if (hres == S_FALSE) {
  104.         CoUninitialize();
  105.     }
  106.  
  107.     if ( !hPrevInstance ) {
  108.         if ( !InitApplication( hInstance ) ) {
  109.             return FALSE;
  110.         }
  111.     }
  112.  
  113.     /*
  114.     ** Perform initializations that apply to a specific instance
  115.     */
  116.     if ( !InitInstance( hInstance, nCmdShow ) ) {
  117.         return FALSE;
  118.     }
  119.  
  120.     // Verify that the Video Mixing Renderer is present (requires Windows XP).
  121.     // Otherwise, this sample cannot continue.
  122.     if (!VerifyVMR())
  123.        return FALSE;
  124.  
  125.     /* Look for options */
  126.     while (lpCmdLine && (*lpCmdLine == '-' || *lpCmdLine == '/')) {
  127.         if (lpCmdLine[1] == 'P') {
  128.             g_bPlay = TRUE;
  129.             lpCmdLine += 2;
  130.         } else {
  131.             break;
  132.         }
  133.         while (lpCmdLine[0] == ' ') {
  134.             lpCmdLine++;
  135.         }
  136.     }
  137.  
  138.     SetFullScreenMode(g_bPlay);
  139.  
  140.     // If the user selects a file, open it and start playing.
  141.     // Otherwise, just exit the app.
  142.     if (ProcessOpen(lpCmdLine, TRUE) == TRUE)
  143.     {
  144.         /*
  145.         ** Acquire and dispatch messages until a WM_QUIT message is received.
  146.         */
  147.         iRet = DoMainLoop();
  148.     }
  149.  
  150.     QzUninitialize();
  151.     return iRet;
  152. }
  153.  
  154. /*****************************Private*Routine******************************\
  155. * DoMainLoop
  156. *
  157. * Process the main message loop
  158. *
  159. \**************************************************************************/
  160. int
  161. DoMainLoop(
  162.     void
  163.     )
  164. {
  165.     MSG         msg;
  166.     HANDLE      ahObjects[8];;
  167.     int         cObjects;
  168.     HACCEL      haccel = LoadAccelerators(g_hInst, MAKEINTRESOURCE(IDR_ACCELERATOR));
  169.  
  170.     //
  171.     // message loop lasts until we get a WM_QUIT message
  172.     // upon which we shall return from the function
  173.     //
  174.     for ( ;; ) {
  175.  
  176.         if (pMpegMovie != NULL) {
  177.             cObjects = 1;
  178.             ahObjects[0] = pMpegMovie->GetMovieEventHandle();
  179.         }
  180.         else {
  181.             ahObjects[0] = NULL;
  182.             cObjects = 0;
  183.         }
  184.  
  185.         if (ahObjects[0] == NULL) {
  186.             WaitMessage();
  187.         }
  188.         else {
  189.  
  190.             //
  191.             // wait for any message sent or posted to this queue
  192.             // or for a graph notification
  193.             //
  194.             DWORD result;
  195.  
  196.             result = MsgWaitForMultipleObjects(cObjects, ahObjects, FALSE,
  197.                                                INFINITE, QS_ALLINPUT);
  198.             
  199.             if (result != (WAIT_OBJECT_0 + cObjects)) {
  200.                 
  201.                 VideoCd_OnGraphNotify(result - WAIT_OBJECT_0);
  202.                 continue;
  203.             }
  204.         }
  205.  
  206.         //
  207.         // When here, we either have a message or no event handle
  208.         // has been created yet.
  209.         //
  210.         // read all of the messages in this next loop
  211.         // removing each message as we read it
  212.         //
  213.  
  214.         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  215.  
  216.             switch( msg.message )
  217.             {
  218.                 case WM_QUIT:
  219.                     return (int) msg.wParam;
  220.                     break;
  221.             }
  222.  
  223.             if (!TranslateAccelerator(hwndApp, haccel, &msg)) {
  224.                 TranslateMessage(&msg);
  225.                 DispatchMessage(&msg);
  226.             }
  227.         }
  228.     }
  229.  
  230. } // DoMainLoop
  231.  
  232.  
  233. /*****************************Private*Routine******************************\
  234. * InitApplication(HANDLE)
  235. *
  236. * This function is called at initialization time only if no other
  237. * instances of the application are running.  This function performs
  238. * initialization tasks that can be done once for any number of running
  239. * instances.
  240. *
  241. * In this case, we initialize a window class by filling out a data
  242. * structure of type WNDCLASS and calling the Windows RegisterClass()
  243. * function.  Since all instances of this application use the same window
  244. * class, we only need to do this when the first instance is initialized.
  245. *
  246. \**************************************************************************/
  247. BOOL
  248. InitApplication(
  249.     HINSTANCE hInstance
  250.     )
  251. {
  252.     WNDCLASS  wc;
  253.  
  254.     /*
  255.     ** Fill in window class structure with parameters that describe the
  256.     ** main window.
  257.     */
  258.     hIconVideoCd     = LoadIcon( hInstance, MAKEINTRESOURCE(IDR_VIDEOCD_ICON) );
  259.  
  260.     wc.style         = CS_VREDRAW | CS_HREDRAW;
  261.     wc.lpfnWndProc   = VideoCdWndProc;
  262.     wc.cbClsExtra    = 0;
  263.     wc.cbWndExtra    = 0;
  264.     wc.hInstance     = hInstance;
  265.     wc.hIcon         = hIconVideoCd;
  266.     wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
  267.     wc.hbrBackground = (HBRUSH)NULL; // (COLOR_BTNFACE + 1);
  268.     wc.lpszMenuName  = MAKEINTRESOURCE( IDR_MAIN_MENU);
  269.     wc.lpszClassName = szClassName;
  270.  
  271.     /*
  272.     ** Register the window class and return success/failure code.
  273.     */
  274.     return RegisterClass( &wc );
  275. }
  276.  
  277.  
  278. /*****************************Private*Routine******************************\
  279. * InitInstance
  280. *
  281. *
  282. * This function is called at initialization time for every instance of
  283. * this application.  This function performs initialization tasks that
  284. * cannot be shared by multiple instances.
  285. *
  286. * In this case, we save the instance handle in a static variable and
  287. * create and display the main program window.
  288. *
  289. \**************************************************************************/
  290. BOOL
  291. InitInstance(
  292.     HINSTANCE hInstance,
  293.     int nCmdShow
  294.     )
  295. {
  296.     HWND    hwnd;
  297.  
  298.     /*
  299.     ** Save the instance handle in static variable, which will be used in
  300.     ** many subsequence calls from this application to Windows.
  301.     */
  302.     g_hInst = hInstance;
  303.  
  304.     /*
  305.     ** Create a hidden window for this application instance.
  306.     */
  307.     hwnd = CreateWindow( szClassName, IdStr(STR_APP_TITLE), g_Style,
  308.                          CW_USEDEFAULT, CW_USEDEFAULT, 
  309.                          CW_USEDEFAULT, CW_USEDEFAULT, 
  310.                          NULL, NULL, hInstance, NULL );
  311.  
  312.     /*
  313.     ** If window could not be created, return "failure"
  314.     */
  315.     if ( NULL == hwnd ) {
  316.         return FALSE;
  317.     }
  318.     hwndApp = hwnd;
  319.  
  320.  
  321.     /*
  322.     ** Keep the main window invisible, since all we need to do is
  323.      * display a FileOpen dialog box.
  324.     */
  325.  
  326.     return TRUE;
  327. }
  328.  
  329.  
  330. /*****************************Private*Routine******************************\
  331. * GetMoviePosition
  332. *
  333. * Place the movie in the centre of the client window.  We do not stretch the
  334. * the movie yet !
  335. *
  336. \**************************************************************************/
  337. void
  338. GetMoviePosition(
  339.     HWND hwnd,
  340.     long* xPos,
  341.     long* yPos,
  342.     long* pcx,
  343.     long* pcy
  344.     )
  345. {
  346.     RECT rc = {0, 0, 400, 300};
  347.  
  348.     GetClientRect(hwnd, &rc);
  349.  
  350.     *xPos = rc.left;
  351.     *yPos = rc.top;
  352.  
  353.     *pcx = rc.right - rc.left;
  354.     *pcy = rc.bottom - rc.top;
  355. }
  356.  
  357.  
  358. /******************************Public*Routine******************************\
  359. * RepositionMovie
  360. *
  361. \**************************************************************************/
  362. void
  363. RepositionMovie(HWND hwnd)
  364. {
  365.     if (pMpegMovie) {
  366.  
  367.         IVMRWindowlessControl* lpDefWC = pMpegMovie->GetWLC();
  368.         if (lpDefWC) {
  369.             LONG w, h;
  370.  
  371.             lpDefWC->GetNativeVideoSize(&w, &h, NULL, NULL);
  372.  
  373.             RECT rc = {(640-w)/2, (480-h)/2, (640+w)/2, (480+h)/2};
  374.  
  375.             lpDefWC->SetVideoPosition(NULL, &rc);
  376.         }
  377.     }
  378. }
  379.  
  380.  
  381. /*****************************Private*Routine******************************\
  382. * VideoCd_OnMove
  383. *
  384. \**************************************************************************/
  385. void
  386. VideoCd_OnMove(
  387.     HWND hwnd,
  388.     int x,
  389.     int y
  390.     )
  391. {
  392.     if (pMpegMovie) {
  393.         if (pMpegMovie->GetStateMovie() != State_Running) {
  394.             RepositionMovie(hwnd);
  395.         }
  396.     }
  397. }
  398.  
  399.  
  400. /******************************Public*Routine******************************\
  401. * VideoCdWndProc
  402. *
  403. \**************************************************************************/
  404. LRESULT CALLBACK
  405. VideoCdWndProc(
  406.     HWND hwnd,
  407.     UINT message,
  408.     WPARAM wParam,
  409.     LPARAM lParam
  410.     )
  411. {
  412.     switch ( message ) {
  413.  
  414.     HANDLE_MSG( hwnd, WM_CREATE,            VideoCd_OnCreate );
  415.     HANDLE_MSG( hwnd, WM_PAINT,             VideoCd_OnPaint );
  416.     HANDLE_MSG( hwnd, WM_CLOSE,             VideoCd_OnClose );
  417.     HANDLE_MSG( hwnd, WM_DESTROY,           VideoCd_OnDestroy );
  418.     HANDLE_MSG( hwnd, WM_SIZE,              VideoCd_OnSize );
  419.     HANDLE_MSG( hwnd, WM_KEYUP,             VideoCd_OnKeyUp);
  420.     HANDLE_MSG( hwnd, WM_MOVE,              VideoCd_OnMove );
  421.  
  422.     case WM_LBUTTONUP:
  423.         {
  424.             VideoCd_OnClick(hwnd, wParam, lParam);
  425.         }
  426.         break;
  427.     case WM_RBUTTONUP:
  428.         {
  429.             VideoCd_OnClickHold(hwnd, wParam, lParam);
  430.         }
  431.         break;
  432.  
  433.     default:
  434.         return DefWindowProc(hwnd, message, wParam, lParam);
  435.     }
  436.  
  437.     return 0L;
  438. }
  439.  
  440.  
  441. /*****************************Private*Routine******************************\
  442. * VideoCd_OnCreate
  443. *
  444. \**************************************************************************/
  445. BOOL
  446. VideoCd_OnCreate(
  447.     HWND hwnd,
  448.     LPCREATESTRUCT lpCreateStruct
  449.     )
  450. {
  451.     return TRUE;
  452. }
  453.  
  454. /*****************************Private*Routine******************************\
  455. * VideoCd_OnKeyUp
  456. *
  457. \**************************************************************************/
  458. void
  459. VideoCd_OnKeyUp(
  460.     HWND hwnd,
  461.     UINT vk,
  462.     BOOL fDown,
  463.     int cRepeat,
  464.     UINT flags
  465.     )
  466. {
  467.     // Catch escape sequences to stop fullscreen mode
  468.     if (vk == VK_ESCAPE) {
  469.  
  470.         if (pMpegMovie) {
  471.             PostMessage(hwnd, WM_CLOSE, 0, 0);
  472.         }
  473.     }
  474. }
  475.  
  476.  
  477. /*****************************Private*Routine******************************\
  478. * VideoCd_OnClick
  479. *
  480. \**************************************************************************/
  481. void
  482. VideoCd_OnClick(
  483.     HWND hwnd,
  484.     WPARAM pParam,
  485.     LPARAM lParam)
  486. {
  487.     int xPos;
  488.     int yPos;
  489.     int nMenuItem = -1;
  490.  
  491.     xPos = GET_X_LPARAM(lParam); 
  492.     yPos = GET_Y_LPARAM(lParam); 
  493.  
  494.     g_ss.bShowHelp = false;
  495.     g_ss.nXHelp = 0;
  496.     g_ss.nYHelp = 0;
  497.     lstrcpy( g_ss.achHelp, TEXT(""));
  498.  
  499.     if( xPos >= 3  && xPos <= 55 )
  500.     {
  501.         nMenuItem = (yPos -6)/53;
  502.         if( nMenuItem == 8 )
  503.         {
  504.             nMenuItem = -1;
  505.         }
  506.     }
  507.  
  508.     switch( nMenuItem)
  509.     {
  510.         case evxMovieRotateZ:
  511.             g_ss.bShowTwist = false;
  512.             g_ss.nDy = 0;
  513.             g_ss.bRotateZ = !(g_ss.bRotateZ);
  514.             break;
  515.         case evxMovieRotateY:
  516.             g_ss.bShowTwist = false;
  517.             g_ss.nDy = 0;
  518.             g_ss.bRotateY = !(g_ss.bRotateY);
  519.             break;
  520.         case evxMovieTwist:
  521.             g_ss.bShowTwist = !(g_ss.bShowTwist);
  522.             break;
  523.         case evxExit:
  524.             if (pMpegMovie) 
  525.             {
  526.                 PostMessage(hwnd, WM_CLOSE, 0, 0);
  527.             }
  528.             break;
  529.         case evxMoviePause:
  530.             if( pMpegMovie )
  531.             {
  532.                 pMpegMovie->PauseMovie();
  533.             }
  534.             break;
  535.         case evxMoviePlay:
  536.             if( pMpegMovie )
  537.             {
  538.                 pMpegMovie->PlayMovie();
  539.             }
  540.             break;
  541.         case evxShowInfo:
  542.             g_ss.bShowStatistics = !(g_ss.bShowStatistics);
  543.             break;
  544.     }// switch
  545. }
  546.  
  547. /*****************************Private*Routine******************************\
  548. * VideoCd_OnClickHold
  549. *
  550. \**************************************************************************/
  551. void
  552. VideoCd_OnClickHold(
  553.     HWND hwnd,
  554.     WPARAM pParam,
  555.     LPARAM lParam)
  556. {
  557.     int xPos;
  558.     int yPos;
  559.     int nMenuItem = -1;
  560.  
  561.     OutputDebugString("*** Event is captured\n");
  562.  
  563.     xPos = GET_X_LPARAM(lParam); 
  564.     yPos = GET_Y_LPARAM(lParam); 
  565.  
  566.     g_ss.bShowHelp = false;
  567.     g_ss.nXHelp = 0;
  568.     g_ss.nYHelp = 0;
  569.     lstrcpy( g_ss.achHelp, TEXT(""));
  570.  
  571.     if( xPos >= 3  && xPos <= 55 )
  572.     {
  573.         nMenuItem = (yPos -6)/53;
  574.         g_ss.bShowHelp = true;
  575.         if( nMenuItem == 8 )
  576.         {
  577.             nMenuItem = -1;
  578.             g_ss.bShowHelp = false;
  579.         }
  580.         
  581.     }
  582.     if( g_ss.bShowHelp )
  583.     {
  584.         OutputDebugString("*** WILL show help\n");
  585.     }
  586.     else
  587.     {
  588.         OutputDebugString("*** WILL NOT show help\n");
  589.     }
  590.  
  591.     switch( nMenuItem)
  592.     {
  593.         case evxMovieRotateZ:
  594.             g_ss.nXHelp = 70;
  595.             g_ss.nYHelp = yPos;
  596.             lstrcpy( g_ss.achHelp, TEXT("Rotate around Z axis "));
  597.             break;
  598.         case evxMovieRotateY:
  599.             g_ss.nXHelp = 70;
  600.             g_ss.nYHelp = yPos;
  601.             lstrcpy( g_ss.achHelp, TEXT("Rotate around Y axis "));
  602.             break;
  603.         case evxMovieTwist:
  604.             g_ss.nXHelp = 70;
  605.             g_ss.nYHelp = yPos;
  606.             lstrcpy( g_ss.achHelp, TEXT("Non-linear transformation "));
  607.             break;
  608.         case evxExit:
  609.             g_ss.nXHelp = 70;
  610.             g_ss.nYHelp = yPos;
  611.             lstrcpy( g_ss.achHelp, TEXT("Exit application "));
  612.             break;
  613.         case evxMoviePause:
  614.             g_ss.nXHelp = 70;
  615.             g_ss.nYHelp = yPos;
  616.             lstrcpy( g_ss.achHelp, TEXT("Pause "));
  617.             break;
  618.         case evxMoviePlay:
  619.             g_ss.nXHelp = 70;
  620.             g_ss.nYHelp = yPos;
  621.             lstrcpy( g_ss.achHelp, TEXT("Play "));
  622.             break;
  623.         case evxShowInfo:
  624.             g_ss.nXHelp = 70;
  625.             g_ss.nYHelp = yPos;
  626.             lstrcpy( g_ss.achHelp, TEXT("Show statistics "));
  627.             break;
  628.     }// switch
  629. }
  630.  
  631.  
  632. /*****************************Private*Routine******************************\
  633. * VideoCd_OnPaint
  634. *
  635. \**************************************************************************/
  636. void
  637. VideoCd_OnPaint(
  638.     HWND hwnd
  639.     )
  640. {
  641.     PAINTSTRUCT ps;
  642.     HDC         hdc;
  643.     RECT        rc2;
  644.  
  645.     /*
  646.     ** Draw a frame around the movie playback area.
  647.     */
  648.     hdc = BeginPaint( hwnd, &ps );
  649.     GetClientRect(hwnd, &rc2);
  650.     FillRect(hdc, &rc2, (HBRUSH)(COLOR_BTNFACE + 1));
  651.     EndPaint( hwnd, &ps );
  652. }
  653.  
  654.  
  655. /******************************Public*Routine******************************\
  656. * VideoCd_OnDestroy
  657. *
  658. \**************************************************************************/
  659. void
  660. VideoCd_OnDestroy(
  661.     HWND hwnd
  662.     )
  663. {
  664.     PostQuitMessage( 0 );
  665. }
  666.  
  667.  
  668. /******************************Public*Routine******************************\
  669. * VideoCd_OnClose
  670. *
  671. \**************************************************************************/
  672. void
  673. VideoCd_OnClose(
  674.     HWND hwnd
  675.     )
  676. {
  677.     if (pMpegMovie) {
  678.         pMpegMovie->StopMovie();
  679.         pMpegMovie->CloseMovie();
  680.  
  681.         delete pMpegMovie;
  682.         pMpegMovie = NULL;
  683.     }
  684.  
  685.     DestroyWindow( hwnd );
  686. }
  687.  
  688.  
  689. /******************************Public*Routine******************************\
  690. * VideoCd_OnSize
  691. *
  692. \**************************************************************************/
  693. void
  694. VideoCd_OnSize(
  695.     HWND hwnd,
  696.     UINT state,
  697.     int dx,
  698.     int dy
  699.     )
  700. {
  701.     RepositionMovie(hwnd);
  702. }
  703.  
  704.  
  705. /*****************************Private*Routine******************************\
  706. * VideoCd_OnGraphNotify
  707. *
  708. * This is where we get any notifications from the filter graph.
  709. *
  710. \**************************************************************************/
  711. void
  712. VideoCd_OnGraphNotify(
  713.     int stream
  714.     )
  715. {
  716.     long    lEventCode;
  717.  
  718.     lEventCode = pMpegMovie->GetMovieEventCode();
  719.  
  720.     switch (lEventCode) {
  721.         case EC_FULLSCREEN_LOST:
  722.             break;
  723.  
  724.         case EC_COMPLETE:
  725.             // when movie is complete, reposition it to the start position
  726.             pMpegMovie->SeekToPosition(0L,FALSE);
  727.             break;
  728.         case EC_USERABORT:
  729.         case EC_ERRORABORT:
  730.             break;
  731.     }
  732. }
  733.  
  734.  
  735. /******************************Public*Routine******************************\
  736. * IdStr
  737. *
  738. * Loads the given string resource ID into the passed storage.
  739. *
  740. \**************************************************************************/
  741. LPCTSTR
  742. IdStr(
  743.     int idResource
  744.     )
  745. {
  746.     static TCHAR    chBuffer[ STR_MAX_STRING_LEN ];
  747.  
  748.     if (LoadString(g_hInst, idResource, chBuffer, STR_MAX_STRING_LEN) == 0) {
  749.         return g_szEmpty;
  750.     }
  751.  
  752.     return chBuffer;
  753.  
  754. }
  755.  
  756.  
  757. /******************************Public*Routine******************************\
  758. * SetFullScreenMode
  759. *
  760. \**************************************************************************/
  761. void
  762. SetFullScreenMode(BOOL bMode)
  763. {
  764.     g_bFullScreen = bMode;
  765.  
  766.     static HMENU hMenu;
  767.     static LONG  lStyle;
  768.     static int xs, ys, cxs, cys;
  769.  
  770.     HDC hdcScreen = GetDC(NULL);
  771.     int cx = GetDeviceCaps(hdcScreen,HORZRES);
  772.     int cy = GetDeviceCaps(hdcScreen,VERTRES);
  773.     ReleaseDC(NULL, hdcScreen);
  774.  
  775.     if (bMode) {
  776.  
  777.         hMenu = GetMenu(hwndApp);
  778.         lStyle = GetWindowStyle(hwndApp);
  779.  
  780.         WINDOWPLACEMENT wp;
  781.         GetWindowPlacement(hwndApp, &wp);
  782.         xs = wp.rcNormalPosition.left;
  783.         ys = wp.rcNormalPosition.top;
  784.         cxs = wp.rcNormalPosition.right - xs;
  785.         cys = wp.rcNormalPosition.bottom - ys;
  786.         ShowWindow(g_hwndToolbar, SW_HIDE);
  787.         SetMenu(hwndApp, NULL);
  788.         SetWindowLong(hwndApp, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE);
  789.         SetWindowPos(hwndApp, HWND_TOP, 0, 0, cx, cy, SWP_NOACTIVATE);
  790.         ShowCursor(FALSE);
  791.  
  792.     }
  793.     else {
  794.         ShowCursor(TRUE);
  795.         ShowWindow(g_hwndToolbar, SW_SHOW);
  796.         SetMenu(hwndApp, hMenu);
  797.         SetWindowLong(hwndApp, GWL_STYLE, lStyle);
  798.         SetWindowPos(hwndApp, HWND_TOP, xs, ys, cxs, cys, SWP_NOACTIVATE);
  799.     }
  800. }
  801.  
  802.  
  803. /******************************Public*Routine******************************\
  804. * IsFullScreenMode()
  805. *
  806. \**************************************************************************/
  807. BOOL
  808. IsFullScreenMode()
  809. {
  810.     return g_bFullScreen;
  811. }
  812.